package codecs;

import java.awt.Dimension;

import javax.media.Buffer;
import javax.media.Effect;
import javax.media.Format;
import javax.media.ResourceUnavailableException;
import javax.media.format.RGBFormat;
import javax.media.format.VideoFormat;
import javax.media.format.YUVFormat;

/**
 * Effect to show the grid
 * @author	Daniel Mohr, Daniela Grammlich
 */
public class TheGridEffect implements Effect{
	
	/**
	 * The supported input formats
	 */
	private Format[] supportedInput;
	/**
	 * The supported output formats
	 */
	private Format[] supportedOutput;
	
	/**
	 * Defines the color "white" as an hex value
	 */
	private static int white = 0x00ffffff;
	/**
	 * Defines the alpha value
	 */
	private static double alphaChannel = 0.2;
	
	/**
	 * Draw a rectangle of the grid or not?
	 */
	private boolean alphaSwitch = false;
	
	/**
	 * The name of the effect
	 */
	private static String EFFECT_NAME = "The Grid";
	
	public TheGridEffect(){
		supportedInput = new Format[]{
				new VideoFormat(VideoFormat.RGB, new Dimension(320, 240), 
						230400, Format.byteArray, (float) 15.0),
				new RGBFormat(),
				new YUVFormat(),
		};
		supportedOutput = new Format[]{
				new RGBFormat(),
				new YUVFormat(),				
		};
	}
	
	@Override
	public Format[] getSupportedInputFormats() {
		return supportedInput;
	}

	@Override
	public Format[] getSupportedOutputFormats(Format input) {		
		if(input == null) {
			return supportedOutput;
		}
		if(input instanceof RGBFormat) {
			return(new Format[] {   
				input,
				supportedOutput[0],
			});
		} else {
			return(supportedOutput);
		}
	}

	@Override
	public int process(Buffer inputBuffer, Buffer outputBuffer) {
		outputBuffer.copy(inputBuffer);

		int[] outputData = (int[]) outputBuffer.getData();
		
		RGBFormat videoFormatIn = (RGBFormat) inputBuffer.getFormat();
		int redMask = videoFormatIn.getRedMask();
		int blueMask = videoFormatIn.getBlueMask();
		int greenMask = videoFormatIn.getGreenMask();
		
		/* Dimension of the incoming stream */
		Dimension sizeIn = videoFormatIn.getSize();
		int height = (int) sizeIn.getHeight();
		int width = (int) sizeIn.getWidth();
		
		int pixelData;
		
		/* Drawing the grid on the image stream */
		for(int x = 0; x < width; x++){
			for(int y = 0; y < height; y++){
				if(alphaSwitch){
					/* Draws a rectangle */
					pixelData = ((int)((outputData[x + width * y] & redMask) * 
							(1 - alphaChannel) + white * (alphaChannel))) & redMask;
					pixelData += ((int)((outputData[x + width * y] & greenMask) * 
							(1 - alphaChannel) + white * (alphaChannel))) & greenMask;
					pixelData += ((int)((outputData[x + width * y] & blueMask) * 
							(1 - alphaChannel) + white * (alphaChannel))) & blueMask;
					outputData[x + width * y] = pixelData;
				}
				if(y % 16 == 0) {
					alphaSwitch = !alphaSwitch;
				}
			}
			if(x % 16 == 0) {
				alphaSwitch = !alphaSwitch;
			}
		}
		
		return BUFFER_PROCESSED_OK;
	}

	@Override
	public Format setInputFormat(Format inputFormat) {
		if (inputFormat instanceof RGBFormat) inputFormat = (RGBFormat)inputFormat;
		else inputFormat = (RGBFormat)supportedInput[0];
		return(inputFormat);
	}

	@Override
	public Format setOutputFormat(Format outputFormat) {
		if (outputFormat instanceof RGBFormat) outputFormat = (RGBFormat)outputFormat;
		else outputFormat = (RGBFormat)supportedOutput[0];
		return(outputFormat);
	}

	@Override
	public void close() {
	}

	@Override
	public String getName() {
		return EFFECT_NAME;
	}

	@Override
	public void open() throws ResourceUnavailableException {	
	}

	@Override
	public void reset() {
	}

	@Override
	public Object getControl(String arg0) {		
		return null;
	}

	@Override
	public Object[] getControls() {		
		return null;
	}

}
